//
//  Factory.m
//  CocoaSynth
//
//  Created by Simon André on 17/02/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "Factory.h"
#import "Module.h"
#import "ModuleKeyboardProtocol.h"
#import "ModuleVCOProtocol.h"
#import "ModuleVCFProtocol.h"
#import "ModuleVCAProtocol.h"
#import "ModuleADSRProtocol.h"
#import "ModuleSpeakerProtocol.h"
#import "ModuleWriterProtocol.h"
#import "ModuleMixerProtocol.h"
#import "ConnectorProtocol.h"
#import "ModuleViewController.h"

#import "ModuleKeyboard.h"
#import "ModuleVCO.h"
#import "ModuleVCF.h"
#import "ModuleVCA.h"
#import "ModuleADSR.h"
#import "ModuleSpeaker.h"
#import "ModuleWriter.h"
#import "ModuleDispatcher.h"
#import "ModuleMixer.h"
#import "Connector.h"

#import "ModuleVCOViewController.h"
#import "ModuleVCFViewController.h"
#import "ModuleVCAViewController.h"
#import "ModuleADSRViewController.h"
#import "ModuleSpeakerViewController.h"
#import "ModuleKeyboardViewController.h"
#import "ModuleDispatcherViewController.h"
#import "ModuleMixerViewController.h"
#import "ModuleWriterViewController.h"

#import "PortOut.h"
#import "PortOutProtocol.h"
#import "SinusoidGenerator.h"
#import "SawtoothGenerator.h"
#import "SquareGenerator.h"
#import "LowpassFilter.h"
#import "VCAAlgorithm.h"
#import "ADSRGenerator.h"
#import "MixingStrategy.h"
#import "ComputingStrategyProtocol.h"
#import "PortIn.h"
#import "PortInProtocol.h"

@implementation Factory


+ (ModuleViewController*)createVCO
{
	Module<ModuleVCOProtocol>* module = [[ModuleVCO alloc] init];
	ModuleViewController* controller = [[ModuleVCOViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	
	id<PortOutProtocol> portOutSinusoid = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategySinusoid = [[[SinusoidGenerator alloc] init] autorelease];
	[strategySinusoid setModule:module];
	[portOutSinusoid setComputingStrategy:strategySinusoid];
	[module addPortOut:portOutSinusoid];
	[portOutSinusoid setModule:module];
	
	id<PortOutProtocol> portOutSawtooth = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategySawtooth = [[[SawtoothGenerator alloc] init] autorelease];
	[strategySawtooth setModule:module];
	[portOutSawtooth setComputingStrategy:strategySawtooth];
	[module addPortOut:portOutSawtooth];
	[portOutSawtooth setModule:module];
	
	id<PortOutProtocol> portOutSquare = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategySquare = [[[SquareGenerator alloc] init] autorelease];
	[strategySquare setModule:module];
	[portOutSquare setComputingStrategy:strategySquare];
	[module addPortOut:portOutSquare];
	[portOutSquare setModule:module];
	
	[module setBaseFrequency:1024.f];
	[module setExponentialFrequency:0.f];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createVCF
{
	Module<ModuleVCFProtocol>* module = [[ModuleVCF alloc] init];
	ModuleViewController* controller = [[ModuleVCFViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	id<PortInProtocol> portFm = [[PortIn alloc] init];
	[module setPortIn:portIn];
	[module setCutOffFrequencyPort:portFm];
	
	id<PortOutProtocol> portOutLowpass = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategylowpass = [[[LowpassFilter alloc] init] autorelease];
	[strategylowpass setModule:module];
	[portOutLowpass setComputingStrategy:strategylowpass];
	[module addPortOut:portOutLowpass];
	
	[portOutLowpass setModule:module];
	
	[module setInputFrequencyModificator:1.f];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createVCA
{
	Module<ModuleVCAProtocol>* module = [[ModuleVCA alloc] init];
	ModuleViewController* controller = [[ModuleVCAViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	id<PortInProtocol> portControl = [[PortIn alloc] init];
	[module setPortIn:portIn];
	[module setPortInAm:portControl];
	
	id<PortOutProtocol> portOut = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategy = [[[VCAAlgorithm alloc] init] autorelease];
	[strategy setModule:module];
	[portOut setComputingStrategy:strategy];
	[module addPortOut:portOut];
	
	[portOut setModule:module];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createADSR
{
	Module<ModuleADSRProtocol>* module = [[ModuleADSR alloc] init];
	ModuleViewController* controller = [[ModuleADSRViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	
	id<PortOutProtocol> portOut = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategy = [[[ADSRGenerator alloc] init] autorelease];
	[strategy setModule:module];
	[portOut setComputingStrategy:strategy];
	[module addPortOut:portOut];
	
	[portOut setModule:module];
	
	[module setAttack:0.5];
	[module setDecay:0.25];
	[module setSustain:0.5];
	[module setRelease:0.5];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}


+ (ModuleViewController*)createSpeaker
{
	Module<ModuleSpeakerProtocol>* module = [[ModuleSpeaker alloc] init];
	ModuleViewController* controller = [[ModuleSpeakerViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createWriter
{
	Module<ModuleWriterProtocol>* module = [[ModuleWriter alloc] init];
	ModuleViewController* controller = [[ModuleWriterViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createKeyboard
{
	Module<ModuleKeyboardProtocol>* module = [[ModuleKeyboard alloc] init];
	ModuleViewController* controller = [[ModuleKeyboardViewController alloc] init];
	
	id<PortOutProtocol> portOut = [[PortOut alloc] init];
	[module addPortOut:portOut];
	
	[portOut setModule:module];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createDispatcher
{
	Module* module = [[ModuleDispatcher alloc] init];
	ModuleViewController* controller = [[ModuleDispatcherViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	
	id<PortOutProtocol> portOut1 = [[PortOut alloc] init];
	[portOut1 setModule:module];
	[portOut1 setDispatcher:YES];
	[module addPortOut:portOut1];
	
	id<PortOutProtocol> portOut2 = [[PortOut alloc] init];
	[portOut2 setModule:module];
	[portOut2 setDispatcher:YES];
	[module addPortOut:portOut2];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (ModuleViewController*)createMixer
{
	Module<ModuleMixerProtocol>* module = [[ModuleMixer alloc] init];
	ModuleViewController* controller = [[ModuleMixerViewController alloc] init];
	
	id<PortInProtocol> portIn = [[PortIn alloc] init];
	[module setPortIn:portIn];
	id<PortInProtocol> portIn2 = [[PortIn alloc] init];
	[module setPortIn2:portIn2];
	
	id<PortOutProtocol> portOut = [[PortOut alloc] init];
	id<ComputingStrategyProtocol> strategy = [[[MixingStrategy alloc] init] autorelease];
	[strategy setModule:module];
	[portOut setComputingStrategy:strategy];
	[module addPortOut:portOut];
	
	[portOut setModule:module];
	
	[controller setModel:module];
	[module release];
	[controller autorelease];
	return controller;
}

+ (id<ConnectorProtocol>)createConnector
{
	id<ConnectorProtocol> connector = [[Connector alloc] init];
	[connector autorelease];
	return connector;
}


@end
